package messenger;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

import chatServer.ChatPacket;

/**
 * @author (Group 42) William Orem, Joseph Hamilton, Kevin Benik
 *
 */
public class CommChannel extends Thread implements Runnable {

	private Socket socket = null;
	public CommCommand command = CommCommand.WAIT;
	private UserAccount user = null;
	public Message outMessage = null;
	private String findUser;
	private ArrayList<Contact> tmpContacts = new ArrayList<Contact>();

	/**
	 * @param serverName
	 * @param serverPort
	 * @param user
	 */
	public CommChannel(String serverName, int serverPort, UserAccount user) {
		System.out.print("Establishing connection. Please wait ...");
		try {
			socket = new Socket(serverName, serverPort);
			System.out.println("Connected: " + socket);
			this.user = user;
		} catch (UnknownHostException e) {
			System.out.println("Host unknown: " + e.getMessage());
		} catch (IOException e) {
			System.out.println("Unexpected exception: " + e.getMessage());
		}
	}

	/**
	 * @returns the chatpacket for the login event
	 */
	public ChatPacket doLogin() {
		ChatPacket tmp = new ChatPacket(CommCommand.LOGIN);
		tmp.setMsg(0, user.userName);
		tmp.setMsg(1, user.getPassword());
		return tmp;
	}

	/**
	 * @return the command
	 */
	public CommCommand getCommand() {
		return command;
	}

	/**
	 * @return the findUser
	 */
	public String getFindUser() {
		return findUser;
	}


	/**
	 * @param in
	 * @throws ClassNotFoundException
	 * @throws IOException
	 * Process the input from the server 
	 */
	@SuppressWarnings("unchecked")
	public void proccessInput(ObjectInputStream in)
			throws ClassNotFoundException, IOException {
		ChatPacket inPacket = null;
		CommCommand inCommand = CommCommand.WAIT;
		if (in != null) {
			inPacket = (ChatPacket) in.readObject();
			inCommand = inPacket.getCommand();
		}
		switch (inCommand) {
		case ADDCCONTACT:

			break;
		case GETALL:
			tmpContacts.clear();
			tmpContacts.addAll((ArrayList<Contact>) inPacket.getMsgs());
			break;
		case GETCONTACT:
			System.out.println("Found user "
					+ ((Contact) inPacket.getMsg(0)).userName);
			if (user.findContact(((Contact) inPacket.getMsg(0)).userName) == null)
				user.getContacts().add((Contact) inPacket.getMsg(0));
			break;
		case LOGIN:
			break;
		case SEND:
			user.getTmpMessages().addAll(
					(ArrayList<Message>) inPacket.getMsgs());
			break;
		case STAT:
			break;
		case OK:
			// System.out.println("Logged in");
			break;
		case HELO:
			// command=CommCommand.LOGIN;
			//System.out.println("got HELO");
			break;
		default:
			break;

		}

	}

	/**
	 * @param out
	 * @throws IOException
	 * process the output to the server
	 */
	public void proccessOutput(ObjectOutputStream out) throws IOException {
		ChatPacket outPacket = null;
		switch (command) {
		case ADDCCONTACT:
			outPacket = sendContact();
			System.out.println("Sending contact to server");
			break;
		case GETALL:
			outPacket = new ChatPacket(CommCommand.GETALL);
			outPacket.setMsg(0, findUser);
			break;
		case GETCONTACT:
			outPacket = new ChatPacket(CommCommand.GETCONTACT);
			outPacket.setMsg(0, findUser);
			break;
		case LOGIN:
			outPacket = doLogin();
			System.out.println("sending login");
			break;
		case SEND:
			outPacket = new ChatPacket(CommCommand.SEND);
			outPacket.setMsg(0, outMessage);
			break;
		case STAT:
			break;
		default:
			outPacket = new ChatPacket(CommCommand.OK);
			outPacket.setMsg(0, "OK");
			break;

		}
		if (outPacket != null) {
			out.writeObject(outPacket);
			out.flush();
			command = CommCommand.WAIT;
		}

	}

	/* (non-Javadoc)
	 * @see java.lang.Thread#run()
	 */
	public void run() {
		try {

			ObjectOutputStream out = new ObjectOutputStream(
					socket.getOutputStream());
			ObjectInputStream in = new ObjectInputStream(
					socket.getInputStream());

			while (in != null && command != CommCommand.QUIT) {
				proccessInput(in);
				if (command != null)
					proccessOutput(out);
				sleep(500);
				// add delay
			}
			in.close();
			out.close();
			socket.close();
		} catch (IOException | ClassNotFoundException | InterruptedException e) {
			System.err.println("no server found or server disconnected");
		}
	}

	/**
	 * @return ChatPacket of addcontact
	 */
	public ChatPacket sendContact() {
		ChatPacket outPacket = new ChatPacket(CommCommand.ADDCCONTACT);
		outPacket.setMsg(0, user.getPassword());
		Contact me = new Contact(user.getpId(), user.getFirstName(),
				user.getLastName(), user.getPhone(), user.geteMail(),
				user.getYear(), user.getUserName());
		outPacket.setMsg(1, me);
		return outPacket;
	}

	/**
	 * @param command
	 *            the command to set
	 */
	public void setCommand(CommCommand command) {
		this.command = command;
	}

	/**
	 * @param findUser
	 *            the findUser to set
	 */
	public void setFindUser(String findUser) {
		this.findUser = findUser;
	}

	/**
	 * @param outMessage
	 *            the outMessage to set
	 */
	public void setOutMessage(Message outMessage) {
		this.outMessage = outMessage;
	}

	/**
	 * @param user
	 *            the user to set
	 */
	public void setUser(UserAccount user) {
		this.user = user;
	}

	/**
	 * @return the tmpContacts
	 */
	public ArrayList<Contact> getTmpContacts() {
		return tmpContacts;
	}

}
